#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "xaux_object.h"

static int xaux_so_Create(aux_t *);
static int xaux_so_Start(aux_t *, const unsigned char *, int size);
static int xaux_so_Draw(aux_t *, const unsigned char *, int size);
static int xaux_so_Done(aux_t *, const unsigned char *, int size);
static int xaux_so_Switched(aux_t *, int im_id, int on_off);
static int xaux_so_Destroy(aux_t *);
static int xaux_so_GetValuesReply(aux_t *, const unsigned char *, int);
static int xaux_so_DestroyIC(aux_t *);
static int xaux_so_SetICFocus(aux_t *);
static int xaux_so_UnsetICFocus(aux_t *);

aux_method_t xaux_so_methods = {
	xaux_so_Create,
	xaux_so_Start,
	xaux_so_Draw,
	xaux_so_Done,
	xaux_so_Switched,
	xaux_so_Destroy,
	xaux_so_GetValuesReply,
	xaux_so_DestroyIC,
	xaux_so_SetICFocus,
	xaux_so_UnsetICFocus
};

#ifdef USE_AUX_IF_VERSION_2 

static Bool register_aux_modules(unsigned int if_version, aux_service_t *service);

aux_info_t aux_info = { 
	AUX_IF_VERSION_2,	/* if_version       */
	register_aux_modules,	/* register_service */
	NULL			/* aux_dir          */
};

extern aux_dir_t *aux_dir_init();

static Bool register_aux_modules(unsigned int if_version, aux_service_t *service)
{
	DEBUG_printf("register_service =========================\n");

	/* get aux_object module informations */
	aux_info.dir = (aux_dir_t *)aux_dir_init();
	return (True);
}

#endif

extern xaux_class_t xaux_classes[];

static xaux_object_t *xaux_object_inst = NULL;

/* to avoid memory leak problem since xaux_so_Destroy is not called */
#ifndef USE_XAUX_OBJECT_MALLOC
static xaux_object_t xaux_object_real;
#endif

static int xaux_so_Create(aux_t *aux)
{
	DEBUG_printf("xaux_so_Create aux: 0x%x======================\n", aux);

	/* initialize some communication atoms and start aux manager */
	if (xaux_object_inst != NULL)
		return (True);

#ifdef USE_XAUX_OBJECT_MALLOC
	xaux_object_inst = (xaux_object_t *)xaux_object_new();
	if (xaux_object_inst == NULL)
		return (False);
#else
	xaux_object_inst = &xaux_object_real;
	memset(xaux_object_inst, 0, sizeof (xaux_object_t));
#endif

	return (xaux_object_init(xaux_object_inst, aux, XAUX_OBJECT_CLASS_NAME, xaux_classes));
}

static int xaux_so_Start(aux_t *aux, const unsigned char *p, int size)
{
	aux_data_t *aux_data;
	char *classname;

	DEBUG_printf("xaux_so_Start aux: 0x%x======================\n", aux);

	aux_data = aux->service->decompose(AUX_DATA_START, p);
	if (aux_data == NULL) return(False);

	/* get aux classname */
        classname = (char *)xaux_object_get_classname_from_utfname((const CARD16 *)aux_data->aux_name,
								   aux_data->aux_name_length);

	DEBUG_printf("so_Start[%s] im:0x%x ic:0x%x\n",
		classname, aux_data->im, aux_data->ic);

	xaux_object_draw_aux_module(xaux_object_inst, aux, classname, aux_data, AUX_DATA_START);

	aux->service->decompose_free(aux_data);
        if (classname) free((char *)classname);

	return (True);
}

static int xaux_so_Draw(aux_t *aux, const unsigned char *p, int size)
{
	aux_data_t *aux_data;
	char *classname;

	DEBUG_printf("xaux_so_Draw aux: 0x%x======================\n", aux);

	aux_data = aux->service->decompose(AUX_DATA_DRAW, p);
	if (aux_data == NULL) return(False);

	/* get aux classname */
        classname = (char *)xaux_object_get_classname_from_utfname((const CARD16 *)aux_data->aux_name,
								   aux_data->aux_name_length);

	DEBUG_printf("so_Draw: integer_count:%d, string_count:%d\n",
			aux_data->integer_count,aux_data->string_count);

	xaux_object_draw_aux_module(xaux_object_inst, aux, classname, aux_data, AUX_DATA_DRAW);

	aux->service->decompose_free(aux_data);
        if (classname) free((char *)classname);

	return (True);
}

static int xaux_so_Done(aux_t* aux, const unsigned char *p, int size)
{
	aux_data_t	* aux_data;
	char *classname;

	DEBUG_printf("xaux_so_Done aux: 0x%x======================\n", aux);

	aux_data = aux->service->decompose(AUX_DATA_DONE, p);
	if (aux_data == NULL) return(False);

	/* get aux classname */
        classname = (char *)xaux_object_get_classname_from_utfname((const CARD16 *)aux_data->aux_name,
								   aux_data->aux_name_length);

	DEBUG_printf("so_Done[%s] im:0x%x ic:0x%x\n",
		classname, aux_data->im, aux_data->ic);

	xaux_object_draw_aux_module(xaux_object_inst, aux, classname, aux_data, AUX_DATA_DONE);

	aux->service->decompose_free(aux_data);
        if (classname) free((char *)classname);

	return (True);
}

static int xaux_so_Switched(aux_t* aux, int im_id, int on_off)
{
	return (True);
}

static int xaux_so_Destroy(aux_t* aux)
{
	DEBUG_printf("xaux_so_Destroy ====== \n");
	xaux_object_destroy(xaux_object_inst);

#ifdef USE_XAUX_OBJECT_MALLOC
	free ((char *)xaux_object_inst);
#endif
	xaux_object_inst = NULL;
	return (True);
}

static int xaux_so_GetValuesReply(aux_t *aux, const unsigned char *p, int size)
{
	return (True);
}

static int xaux_so_DestroyIC(aux_t *aux)
{
	DEBUG_printf("xaux_so_DestroyIC ====== \n");
	return (True);
}

static int xaux_so_SetICFocus(aux_t *aux)
{
	return (True);
}

static int xaux_so_UnsetICFocus(aux_t *aux)
{
	return (True);
}
